home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / lib / python2.5 / csv.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2007-05-11  |  11.8 KB  |  424 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.5)
  3.  
  4. '''
  5. csv.py - read/write/investigate CSV files
  6. '''
  7. import re
  8. from _csv import Error, __version__, writer, reader, register_dialect, unregister_dialect, get_dialect, list_dialects, field_size_limit, QUOTE_MINIMAL, QUOTE_ALL, QUOTE_NONNUMERIC, QUOTE_NONE, __doc__
  9. from _csv import Dialect as _Dialect
  10.  
  11. try:
  12.     from cStringIO import StringIO
  13. except ImportError:
  14.     from StringIO import StringIO
  15.  
  16. __all__ = [
  17.     'QUOTE_MINIMAL',
  18.     'QUOTE_ALL',
  19.     'QUOTE_NONNUMERIC',
  20.     'QUOTE_NONE',
  21.     'Error',
  22.     'Dialect',
  23.     'excel',
  24.     'excel_tab',
  25.     'reader',
  26.     'writer',
  27.     'register_dialect',
  28.     'get_dialect',
  29.     'list_dialects',
  30.     'Sniffer',
  31.     'unregister_dialect',
  32.     '__version__',
  33.     'DictReader',
  34.     'DictWriter']
  35.  
  36. class Dialect:
  37.     '''Describe an Excel dialect.
  38.  
  39.     This must be subclassed (see csv.excel).  Valid attributes are:
  40.     delimiter, quotechar, escapechar, doublequote, skipinitialspace,
  41.     lineterminator, quoting.
  42.  
  43.     '''
  44.     _name = ''
  45.     _valid = False
  46.     delimiter = None
  47.     quotechar = None
  48.     escapechar = None
  49.     doublequote = None
  50.     skipinitialspace = None
  51.     lineterminator = None
  52.     quoting = None
  53.     
  54.     def __init__(self):
  55.         if self.__class__ != Dialect:
  56.             self._valid = True
  57.         
  58.         self._validate()
  59.  
  60.     
  61.     def _validate(self):
  62.         
  63.         try:
  64.             _Dialect(self)
  65.         except TypeError:
  66.             e = None
  67.             raise Error(str(e))
  68.  
  69.  
  70.  
  71.  
  72. class excel(Dialect):
  73.     '''Describe the usual properties of Excel-generated CSV files.'''
  74.     delimiter = ','
  75.     quotechar = '"'
  76.     doublequote = True
  77.     skipinitialspace = False
  78.     lineterminator = '\r\n'
  79.     quoting = QUOTE_MINIMAL
  80.  
  81. register_dialect('excel', excel)
  82.  
  83. class excel_tab(excel):
  84.     '''Describe the usual properties of Excel-generated TAB-delimited files.'''
  85.     delimiter = '\t'
  86.  
  87. register_dialect('excel-tab', excel_tab)
  88.  
  89. class DictReader:
  90.     
  91.     def __init__(self, f, fieldnames = None, restkey = None, restval = None, dialect = 'excel', *args, **kwds):
  92.         self.fieldnames = fieldnames
  93.         self.restkey = restkey
  94.         self.restval = restval
  95.         self.reader = reader(f, dialect, *args, **kwds)
  96.  
  97.     
  98.     def __iter__(self):
  99.         return self
  100.  
  101.     
  102.     def next(self):
  103.         row = self.reader.next()
  104.         if self.fieldnames is None:
  105.             self.fieldnames = row
  106.             row = self.reader.next()
  107.         
  108.         while row == []:
  109.             row = self.reader.next()
  110.         d = dict(zip(self.fieldnames, row))
  111.         lf = len(self.fieldnames)
  112.         lr = len(row)
  113.         if lf < lr:
  114.             d[self.restkey] = row[lf:]
  115.         elif lf > lr:
  116.             for key in self.fieldnames[lr:]:
  117.                 d[key] = self.restval
  118.             
  119.         
  120.         return d
  121.  
  122.  
  123.  
  124. class DictWriter:
  125.     
  126.     def __init__(self, f, fieldnames, restval = '', extrasaction = 'raise', dialect = 'excel', *args, **kwds):
  127.         self.fieldnames = fieldnames
  128.         self.restval = restval
  129.         if extrasaction.lower() not in ('raise', 'ignore'):
  130.             raise ValueError, "extrasaction (%s) must be 'raise' or 'ignore'" % extrasaction
  131.         
  132.         self.extrasaction = extrasaction
  133.         self.writer = writer(f, dialect, *args, **kwds)
  134.  
  135.     
  136.     def _dict_to_list(self, rowdict):
  137.         if self.extrasaction == 'raise':
  138.             for k in rowdict.keys():
  139.                 if k not in self.fieldnames:
  140.                     raise ValueError, 'dict contains fields not in fieldnames'
  141.                     continue
  142.             
  143.         
  144.         return [ rowdict.get(key, self.restval) for key in self.fieldnames ]
  145.  
  146.     
  147.     def writerow(self, rowdict):
  148.         return self.writer.writerow(self._dict_to_list(rowdict))
  149.  
  150.     
  151.     def writerows(self, rowdicts):
  152.         rows = []
  153.         for rowdict in rowdicts:
  154.             rows.append(self._dict_to_list(rowdict))
  155.         
  156.         return self.writer.writerows(rows)
  157.  
  158.  
  159.  
  160. try:
  161.     complex
  162. except NameError:
  163.     complex = float
  164.  
  165.  
  166. class Sniffer:
  167.     '''
  168.     "Sniffs" the format of a CSV file (i.e. delimiter, quotechar)
  169.     Returns a Dialect object.
  170.     '''
  171.     
  172.     def __init__(self):
  173.         self.preferred = [
  174.             ',',
  175.             '\t',
  176.             ';',
  177.             ' ',
  178.             ':']
  179.  
  180.     
  181.     def sniff(self, sample, delimiters = None):
  182.         '''
  183.         Returns a dialect (or None) corresponding to the sample
  184.         '''
  185.         (quotechar, delimiter, skipinitialspace) = self._guess_quote_and_delimiter(sample, delimiters)
  186.         if not delimiter:
  187.             (delimiter, skipinitialspace) = self._guess_delimiter(sample, delimiters)
  188.         
  189.         if not delimiter:
  190.             raise Error, 'Could not determine delimiter'
  191.         
  192.         
  193.         class dialect(Dialect):
  194.             _name = 'sniffed'
  195.             lineterminator = '\r\n'
  196.             quoting = QUOTE_MINIMAL
  197.             doublequote = False
  198.  
  199.         dialect.delimiter = delimiter
  200.         if not quotechar:
  201.             pass
  202.         dialect.quotechar = '"'
  203.         dialect.skipinitialspace = skipinitialspace
  204.         return dialect
  205.  
  206.     
  207.     def _guess_quote_and_delimiter(self, data, delimiters):
  208.         """
  209.         Looks for text enclosed between two identical quotes
  210.         (the probable quotechar) which are preceded and followed
  211.         by the same character (the probable delimiter).
  212.         For example:
  213.                          ,'some text',
  214.         The quote with the most wins, same with the delimiter.
  215.         If there is no quotechar the delimiter can't be determined
  216.         this way.
  217.         """
  218.         matches = []
  219.         for restr in ('(?P<delim>[^\\w\n"\'])(?P<space> ?)(?P<quote>["\']).*?(?P=quote)(?P=delim)', '(?:^|\n)(?P<quote>["\']).*?(?P=quote)(?P<delim>[^\\w\n"\'])(?P<space> ?)', '(?P<delim>>[^\\w\n"\'])(?P<space> ?)(?P<quote>["\']).*?(?P=quote)(?:$|\n)', '(?:^|\n)(?P<quote>["\']).*?(?P=quote)(?:$|\n)'):
  220.             regexp = re.compile(restr, re.DOTALL | re.MULTILINE)
  221.             matches = regexp.findall(data)
  222.             if matches:
  223.                 break
  224.                 continue
  225.         
  226.         if not matches:
  227.             return ('', None, 0)
  228.         
  229.         quotes = { }
  230.         delims = { }
  231.         spaces = 0
  232.         for m in matches:
  233.             n = regexp.groupindex['quote'] - 1
  234.             key = m[n]
  235.             if key:
  236.                 quotes[key] = quotes.get(key, 0) + 1
  237.             
  238.             
  239.             try:
  240.                 n = regexp.groupindex['delim'] - 1
  241.                 key = m[n]
  242.             except KeyError:
  243.                 continue
  244.  
  245.             if key:
  246.                 if delimiters is None or key in delimiters:
  247.                     delims[key] = delims.get(key, 0) + 1
  248.                 
  249.             
  250.             try:
  251.                 n = regexp.groupindex['space'] - 1
  252.             except KeyError:
  253.                 continue
  254.  
  255.             if m[n]:
  256.                 spaces += 1
  257.                 continue
  258.         
  259.         quotechar = reduce((lambda a, b, quotes = quotes: if not quotes[a] > quotes[b] or a:
  260. passb), quotes.keys())
  261.         if delims:
  262.             delim = reduce((lambda a, b, delims = delims: if not delims[a] > delims[b] or a:
  263. passb), delims.keys())
  264.             skipinitialspace = delims[delim] == spaces
  265.             if delim == '\n':
  266.                 delim = ''
  267.             
  268.         else:
  269.             delim = ''
  270.             skipinitialspace = 0
  271.         return (quotechar, delim, skipinitialspace)
  272.  
  273.     
  274.     def _guess_delimiter(self, data, delimiters):
  275.         """
  276.         The delimiter /should/ occur the same number of times on
  277.         each row. However, due to malformed data, it may not. We don't want
  278.         an all or nothing approach, so we allow for small variations in this
  279.         number.
  280.           1) build a table of the frequency of each character on every line.
  281.           2) build a table of freqencies of this frequency (meta-frequency?),
  282.              e.g.  'x occurred 5 times in 10 rows, 6 times in 1000 rows,
  283.              7 times in 2 rows'
  284.           3) use the mode of the meta-frequency to determine the /expected/
  285.              frequency for that character
  286.           4) find out how often the character actually meets that goal
  287.           5) the character that best meets its goal is the delimiter
  288.         For performance reasons, the data is evaluated in chunks, so it can
  289.         try and evaluate the smallest portion of the data possible, evaluating
  290.         additional chunks as necessary.
  291.         """
  292.         data = filter(None, data.split('\n'))
  293.         ascii = [ chr(c) for c in range(127) ]
  294.         chunkLength = min(10, len(data))
  295.         iteration = 0
  296.         charFrequency = { }
  297.         modes = { }
  298.         delims = { }
  299.         start = 0
  300.         end = min(chunkLength, len(data))
  301.         while start < len(data):
  302.             iteration += 1
  303.             for line in data[start:end]:
  304.                 for char in ascii:
  305.                     metaFrequency = charFrequency.get(char, { })
  306.                     freq = line.count(char)
  307.                     metaFrequency[freq] = metaFrequency.get(freq, 0) + 1
  308.                     charFrequency[char] = metaFrequency
  309.                 
  310.             
  311.             for char in charFrequency.keys():
  312.                 items = charFrequency[char].items()
  313.                 if len(items) > 1:
  314.                     modes[char] = reduce((lambda a, b: if not a[1] > b[1] or a:
  315. passb), items)
  316.                     items.remove(modes[char])
  317.                     modes[char] = (modes[char][0], modes[char][1] - reduce((lambda a, b: (0, a[1] + b[1])), items)[1])
  318.                     continue
  319.                 None if len(items) == 1 and items[0][0] == 0 else []
  320.                 modes[char] = items[0]
  321.             
  322.             modeList = modes.items()
  323.             total = float(chunkLength * iteration)
  324.             consistency = 1
  325.             threshold = 0.9
  326.             while len(delims) == 0 and consistency >= threshold:
  327.                 for k, v in modeList:
  328.                     if v[0] > 0 and v[1] > 0:
  329.                         if v[1] / total >= consistency:
  330.                             pass
  331.                         None if delimiters is None or k in delimiters else k in delimiters
  332.                         continue
  333.                 
  334.                 consistency -= 0.01
  335.             if len(delims) == 1:
  336.                 delim = delims.keys()[0]
  337.                 skipinitialspace = data[0].count(delim) == data[0].count('%c ' % delim)
  338.                 return (delim, skipinitialspace)
  339.             
  340.             start = end
  341.             end += chunkLength
  342.         if not delims:
  343.             return ('', 0)
  344.         
  345.         if len(delims) > 1:
  346.             for d in self.preferred:
  347.                 if d in delims.keys():
  348.                     skipinitialspace = data[0].count(d) == data[0].count('%c ' % d)
  349.                     return (d, skipinitialspace)
  350.                     continue
  351.             
  352.         
  353.         items = [ (v, k) for k, v in delims.items() ]
  354.         items.sort()
  355.         delim = items[-1][1]
  356.         skipinitialspace = data[0].count(delim) == data[0].count('%c ' % delim)
  357.         return (delim, skipinitialspace)
  358.  
  359.     
  360.     def has_header(self, sample):
  361.         rdr = reader(StringIO(sample), self.sniff(sample))
  362.         header = rdr.next()
  363.         columns = len(header)
  364.         columnTypes = { }
  365.         for i in range(columns):
  366.             columnTypes[i] = None
  367.         
  368.         checked = 0
  369.         for row in rdr:
  370.             if checked > 20:
  371.                 break
  372.             
  373.             checked += 1
  374.             if len(row) != columns:
  375.                 continue
  376.             
  377.             for col in columnTypes.keys():
  378.                 for thisType in [
  379.                     int,
  380.                     long,
  381.                     float,
  382.                     complex]:
  383.                     
  384.                     try:
  385.                         thisType(row[col])
  386.                     continue
  387.                     except (ValueError, OverflowError):
  388.                         continue
  389.                     
  390.  
  391.                 else:
  392.                     thisType = len(row[col])
  393.                 if thisType == long:
  394.                     thisType = int
  395.                 
  396.                 if thisType != columnTypes[col]:
  397.                     if columnTypes[col] is None:
  398.                         columnTypes[col] = thisType
  399.                     else:
  400.                         del columnTypes[col]
  401.                 columnTypes[col] is None
  402.             
  403.         
  404.         hasHeader = 0
  405.         for col, colType in columnTypes.items():
  406.             if type(colType) == type(0):
  407.                 if len(header[col]) != colType:
  408.                     hasHeader += 1
  409.                 else:
  410.                     hasHeader -= 1
  411.             len(header[col]) != colType
  412.             
  413.             try:
  414.                 colType(header[col])
  415.             except (ValueError, TypeError):
  416.                 hasHeader += 1
  417.                 continue
  418.  
  419.             hasHeader -= 1
  420.         
  421.         return hasHeader > 0
  422.  
  423.  
  424.